/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2009, Around(J2)ME				                                 **
 **   All rights reserved.                                                   **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the New BSD License which accompanies this    			 **
 **   distribution.											                 **
 **   A copy is found in the textfile LICENSE.txt							 **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Main developers:                                                       **
 **     Juri Strumpflohner		http://blog.js-development.com	             **
 **		Matthias Braunhofer		http://matthias.jimdo.com                    **
 **                                                                          **
 **  **********************************************************************  */

package com.aroundj2me.controller;

import java.util.Stack;

import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;

import com.aroundj2me.model.BackCommand;

/**
 * This class is responsible for managing everything that is displayed on the
 * display of the mobile device. The "screens" displayed are managed with a
 * Stack data-structure. The class is a "Singleton"
 * 
 */
public class ScreenController {
	private static ScreenController instance = null;
	private static final int DELAY = 10;
	private Display display;
	private Stack screens;
	private Command backCommand; // back command shared among views

	private ScreenController() {
		screens = new Stack();
	}

	public static ScreenController getInstance() {
		if (instance == null)
			instance = new ScreenController();
		return instance;
	}

	/**
	 * Destroys the instance of this singleton ScreenController class
	 * 
	 */
	public static void destroyInstance() {
		instance = null;
	}

	/**
	 * Displays an object of type Displayable on the device Display and puts the
	 * current displayed screen on the stack
	 * 
	 * @param d
	 *            Displayable object
	 */
	public void display(Displayable d) {
		if (!skip(this.display.getCurrent()) && !skip(d)) {
			screens.push(this.display.getCurrent());
		}
		this.display.setCurrent(d);
		sleep();
	}

	/**
	 * Automatically adds a back command to the given {@link Displayable}
	 * 
	 * @param d
	 *            the {@link Displayable} to which to add the back command
	 * @param autoHookBackCommand
	 */
	public void display(Displayable d, boolean autoHookBackCommand) {
		if (backCommand == null)
			backCommand = new BackCommand();
		d.removeCommand(backCommand); // remove to not add multiple ones (if
										// already exist)
		d.addCommand(backCommand);
		display(d);
	}

	/**
	 * retrieves the last screen from the top of the stack and displayes it
	 * 
	 */
	public void last() {
		Displayable prevScreen = null;
		if (!screens.isEmpty()) {
			prevScreen = (Displayable) screens.pop();
			this.display.setCurrent(prevScreen);

			sleep();
		}
	}

	/**
	 * Proofs if the Displayable d should be put on the stack or not. Usually
	 * "Alerts" shouldn't be pushed on the stack
	 */
	private boolean skip(Displayable d) {
		boolean tmp = d instanceof Alert;
		return tmp;
	}

	/**
	 * Wait some time for the displayable to be shown
	 */
	private void sleep() {
		try {
			Thread.sleep(DELAY);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally {
		}
	}

	/*
	 * Getters and Setters
	 */
	public void setDisplay(Display d) {
		this.display = d;
	}
}
